using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Globalization;
using System.Xml.Serialization;

namespace TST.SharePoint.Shared
{
    /// <summary>
    /// General representation of a Field. Independent of the datasource.
    /// </summary>
    public class Field : IIdentifiable<string>
    {
        private string _id;
        private string _name;
        private bool _visible;
        private string _displayName;
        private bool _isInternal;
        private string _linkFieldId;
        private CustomProperties _properties;
        protected string _internalID;

        /// <summary>
        /// Constructor.
        /// </summary>
        public Field()
        {
        }

        /// <summary>
        /// Get or set the displayname. If no display name was set, return the Name.
        /// </summary>
        public string DisplayName
        {
            get { if (string.IsNullOrEmpty(_displayName)) return Name; else return _displayName; }
            set { _displayName = value; }
        }

        /// <summary>
        /// Get the properties. These are custom properties for a Field object.
        /// They can be specific for just one field.
        /// </summary>
        public CustomProperties Properties
        {
            get
            {
				// Mou concurreny?
                if (_properties == null)
                    _properties = new CustomProperties();
                return _properties;
            }
        }

        /// <summary>
        /// Get or set the name of the field.
        /// </summary>
        public string Name
        {
            get {
                if (string.IsNullOrEmpty(_name))
                    return _id;
                else
                {
                    return _name;
                }
            }
            set { _name = value; }
        }

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="ID">The ID for the field.</param>
        public Field(string Id)
        {
            _id = Id;
        }

        public string InternalId
        {
            get
            {
                if (string.IsNullOrEmpty(_internalID))
                    return Id;
                else
                    return _internalID;
            }
            set
            {
                _internalID = value;
            }
        }

        /// <summary>
        /// Get or set Visible.
        /// </summary>
        public bool Visible
        {
            get { return _visible; }
            set { _visible = value; }
        }

        /// <summary>
        /// Get or set IsInternal. Used to identify datasource internal fields that should
        /// not be available for consumers of the datasource.
        /// </summary>
        public bool IsInternal
        {
            get { return _isInternal; }
            set { _isInternal = value; }
        }

        /// <summary>
        /// Get or set the field type. Custom enumeration.
        /// </summary>
        public virtual FieldType FieldType
        {
            get {return FieldType.String;}
        }

        public virtual FilterType FilterType
        {
            get { return FilterType.Text; }
        }

        /// <summary>
        /// Get or set the ID of a LinkField. A linkfield is a reference to another field in
        /// the same collection. If this reference is set, the field should be rendered as 
        /// a hyperlink, instead of just rendering the value.
        /// </summary>
        public string LinkFieldId
        {
            get { return _linkFieldId; }
            set { _linkFieldId = value; }
        }

        /// <summary>
        /// Virtual to be overriden by descendants to return the data typed according to the field type.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public virtual object GetTypedValue(object value)
        {
            return value;
        }

        public virtual string GetTypedValueAsString(object value)
        {
            return value as string;
        }

        public virtual string GetTypedValueFormatted(object value)
        {
            return value as string;
        }

        public string DatasetId
        {
            get
            {
                Guid id = Guid.Empty;
                if (GuidUtil.GuidTryParse(InternalId, out id))
                    return id.ToString("B");
                else
                    return Name;
            }
        }

        /// <summary>
        /// Check if the ID is a valid field is.
        /// </summary>
        /// <param name="id">the id to be checked.</param>
        /// <returns>true if the value of 'id' is a valid Guid and is not an empty guid.</returns>
        public static bool IsFieldId(string id)
        {
            return ((!string.IsNullOrEmpty(id)) && (id != Guid.Empty.ToString("B").ToString()));
        }

        public virtual string QueryOptions
        {
            get {return string.Empty;}
        }

        #region IIdentifiable<string> Members

        public string Id
        {
            get { return _id; }
            set { _id = value; }
        }

        #endregion

        /// <summary>
        /// Translate our custom field type values to .NET types that user controls
        /// like a grid understand a data type.
        /// </summary>
        /// <param name="fieldType"></param>
        /// <returns></returns>
        public virtual Type DataType
        {
            get
            {
                return typeof(string);
            }
        }

        internal virtual string GetFilterValue(string value)
        {
            return value;
        }
    }

    public enum FieldType
    {
        String,
        DateTime,
        Number,
        Currency,
        Person,
        PersonMulti,
        Lookup,
        LookupMulti,
        Url,
        Boolean,
        Choice,
        ChoiceMulti,
        Guid,
        File,
        Hyperlink,
        Picture,
        Calculated
    }

    public enum FilterType
    {
        Text,
        User,
        Lookup,
        Boolean,
        Number,
        Currency,
        Unknown,
        DateTime
    }

}
